home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / OVERLOAD.C < prev    next >
C/C++ Source or Header  |  1991-12-21  |  21KB  |  504 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d polygonal solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to handle overloaded operators for the input parser module.         *
  7. * Note this module should be accessed by Input Parser only (InptPrsr.c).     *
  8. *****************************************************************************/
  9.  
  10. #ifdef __MSDOS__
  11. #include <alloc.h>
  12. #endif /* __MSDOS__ */
  13.  
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include "program.h"
  19. #include "allocate.h"
  20. #include "booleang.h"
  21. #include "freeform.h"
  22. #include "geomat3d.h"
  23. #include "inptprsg.h"
  24. #include "inptprsl.h"
  25. #include "objects.h"
  26. #include "overload.h"
  27.  
  28. /* The following table help to decide if the operand are legal for the given */
  29. /* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a    */
  30. /* square matrix of number of object types by number of object types:         */
  31.  
  32. static IritExprType OverLoadDiadicTable[5][9][9] =
  33. /*    POLY_EXPR     NUMERIC_EXPR  VECTOR_EXPR   MATRIX_EXPR  CURVE_EXPR  SURFACE_EXPR   STRING_EXPR  OLST_EXPR    CTLPT_EXPR */
  34. { { /* PLUS */
  35.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  36.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  37.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  38.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  39.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      CURVE_EXPR, NO_EXPR,       NO_EXPR,     NO_EXPR,     CURVE_EXPR },
  40.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  41.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  42.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     OLST_EXPR,   NO_EXPR },
  43.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     CURVE_EXPR, NO_EXPR,       NO_EXPR,     NO_EXPR,     CURVE_EXPR } },
  44.  
  45.   { /* MINUS */
  46.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  47.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  48.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR,  NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  49.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  50.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  51.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  52.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  53.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  54.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  55.  
  56.   { /* MULT */
  57.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         POLY_EXPR,   NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  58.     { NO_EXPR,     NUMERIC_EXPR, VECTOR_EXPR,  MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  59.     { NO_EXPR,     VECTOR_EXPR,  NUMERIC_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  60.     { POLY_EXPR, MATRIX_EXPR,  VECTOR_EXPR,  MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR,  NO_EXPR,     OLST_EXPR,   NO_EXPR },
  61.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         CURVE_EXPR,  NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  62.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         SURFACE_EXPR,NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  63.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  64.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         OLST_EXPR,   NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  65.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  66.  
  67.   { /* DIV */
  68.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  69.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  70.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  71.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  72.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  73.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  74.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  75.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  76.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  77.  
  78.   { /* POWER */
  79.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  80.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,         MATRIX_EXPR, NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  81.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  82.     { NO_EXPR,     MATRIX_EXPR,  NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  83.     { NO_EXPR,     NO_EXPR,      NO_EXPR,         NO_EXPR,      NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  84.     { POLY_EXPR, NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    POLY_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR },
  85.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  86.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR },
  87.     { NO_EXPR,   NO_EXPR,      NO_EXPR,         NO_EXPR,     NO_EXPR,    NO_EXPR,       NO_EXPR,     NO_EXPR,     NO_EXPR } },
  88. };
  89.  
  90. /* The following table help to decide if the operand are legal for the given */
  91. /* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length  */
  92. /* of number of object types:                             */
  93.  
  94. static IritExprType OverLoadMonadicTable[1][9] =
  95. /* POLY_EXPR NUMERIC_EXPR  VECTOR_EXPR    MATRIX_EXPR  CURVE_EXPR  SURFACE_EXPR  STRING_EXPR  OLST_EXPR  CTLPT_EXPR */
  96. { /* UNARMINUS */
  97.   { POLY_EXPR, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR,     NO_EXPR,   NO_EXPR }
  98. };
  99.  
  100. static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
  101.                 IritExprType Left, IritExprType *Result);
  102. static ObjectStruct *ConvSrfToPolys(ParseTree *Srf);
  103.  
  104. /*****************************************************************************
  105. *   Routine to perform type checking on the overloaded operators. Returns    *
  106. * TRUE if legal, and set Result to returned object type.             *
  107. *   Allows multiple types (I.e. VECTOR_EXPR | MATRIX_EXPR is legal input).   *
  108. *   Note output Result may be multiple types as well is a such case.         *
  109. *****************************************************************************/
  110. int OverLoadTypeCheck(int Operator, IritExprType Right, IritExprType Left,
  111.                             IritExprType *Result)
  112. {
  113.     int i, j, NumRightTypes, NumLeftTypes;
  114.     IritExprType TmpResult;
  115.  
  116.     /* Compute how many types are feasible here (input). */
  117.     for (i = 1, NumRightTypes = 0; i < ERROR_EXPR; i <<= 1)
  118.     NumRightTypes += (i & Right) != 0;
  119.     for (i = 1, NumLeftTypes = 0; i < ERROR_EXPR; i <<= 1)
  120.     NumLeftTypes += (i & Left) != 0;
  121.  
  122.     if (NumLeftTypes < 1 || NumRightTypes < 1)
  123.     return FALSE;
  124.     else if (NumLeftTypes == 1 && NumRightTypes == 1)
  125.     return OverLoadTypeCheckAux(Operator, Right, Left, Result);
  126.     else {
  127.     /* More than one type in the input - compute union of the output     */
  128.         /* types and return the union.                         */
  129.     *Result = 0;
  130.         for (i = 1; i < ERROR_EXPR; i <<= 1) if ((i & Right) != 0)
  131.             for (j = 1; j < ERROR_EXPR; j <<= 1) if ((j & Left) != 0) {
  132.         if (!OverLoadTypeCheckAux(Operator,
  133.                       (IritExprType) i,
  134.                       (IritExprType) j,
  135.                       &TmpResult))
  136.             return FALSE;
  137.         *Result |= TmpResult;
  138.             }
  139.     return TRUE;
  140.     }
  141. }
  142.  
  143. /*****************************************************************************
  144. *   Routine to perform type checking on the overloaded operators. Returns    *
  145. * TRUE if legal, and set Result to returned object type.             *
  146. *   Assumes a single type (I.e. VECTOR_EXPR | MATRIX_EXPR is illegal input). *
  147. *****************************************************************************/
  148. static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
  149.                 IritExprType Left, IritExprType *Result)
  150. {
  151.     int i, IRight, ILeft;
  152.  
  153.     for (i = 1, IRight = 0; i < Right; i <<= 1, IRight++);
  154.     for (i = 1, ILeft  = 0; i < Left;  i <<= 1, ILeft++);
  155.  
  156.     switch (Operator) {
  157.     case PLUS:
  158.     case MINUS:
  159.     case MULT:
  160.     case DIV:
  161.     case POWER:
  162.         *Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
  163.                      [IRight][ILeft];
  164.         return *Result != NO_EXPR;
  165.     case UNARMINUS:
  166.         *Result = OverLoadMonadicTable[0][IRight];
  167.         return *Result != NO_EXPR;
  168.     default:
  169.         FatalError("OverLoadTypeCheck: undefined operator\n");
  170.     }
  171.     return FALSE;                    /* Makes warning silent. */
  172. }
  173.  
  174. /*****************************************************************************
  175. *   Routine to evaluate    an monadic or diadic expression. It is assumed the   *
  176. * two operands are valid for the given expression - a test which can be made *
  177. * using OverLoadTypeCheck routine (see above). returned pointer to node with *
  178. * the result, NULL in case of error (should not happen actually).         *
  179. * Root holds the simple sub-expression (Root has the operator). PObj holds   *
  180. * all the currently defined objects available in the system. IError & CError *
  181. * will be set to relevant error if was one.                     *
  182. *****************************************************************************/
  183. ParseTree *OverLoadEvalOper(ParseTree *Root, ParseTree *TempR,
  184.         ParseTree *TempL, InptPrsrEvalErrType *IError, char *CError)
  185. {
  186.     int i,
  187.     OperReversed = FALSE;
  188.     RealType R;
  189.     ParseTree *Temp,
  190.     *RetVal = Root;
  191.     ObjectStruct *TempLObj, *TempRObj;
  192.  
  193.     switch (Root->NodeKind) {              /* Dies if undefined operator. */
  194.     case PLUS:
  195.     case MINUS:
  196.     case MULT:
  197.     case DIV:
  198.     case POWER:
  199.         if (TempR == NULL || TempL == NULL) return NULL;       /* Error! */
  200.         break;
  201.  
  202.     case UNARMINUS:
  203.         if (TempR == NULL) return NULL;               /* Error! */
  204.         break;
  205.  
  206.     default:
  207.         FatalError("OverLoadEvalOper: Undefined operator\n");
  208.     }
  209.  
  210.     /* Make TempL be bigger, so we need handle less cases. */
  211.     if (Root -> NodeKind != UNARMINUS &&
  212.     ((int) TempR -> ObjType) > ((int) TempL -> ObjType)) {
  213.     Temp = TempR;
  214.     TempR = TempL;
  215.     TempL = Temp;
  216.  
  217.     OperReversed = TRUE;
  218.     }
  219.  
  220.     switch (Root->NodeKind) {
  221.     case PLUS:
  222.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  223.         Root->ObjType = NUMERIC_OBJ;
  224.         Root->U.R = TempL->U.R + TempR->U.R;
  225.         }
  226.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  227.         Root->ObjType = VECTOR_OBJ;
  228.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  229.         PT_ADD(Root->U.PObj->U.Vec,
  230.             TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
  231.         }
  232.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  233.         Root->ObjType = MATRIX_OBJ;
  234.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  235.                 MatAddTwo4by4(Root->U.PObj->U.Mat,
  236.             TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
  237.         }
  238.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  239.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  240.         TempLObj = ConvSrfToPolys(TempL);
  241.         TempRObj = ConvSrfToPolys(TempR);
  242.         Root->ObjType = POLY_OBJ;
  243.         Root->U.PObj = BooleanOR(TempLObj, TempRObj);
  244.         if (Root->U.PObj == NULL) {
  245.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  246.             UpdateCharError("Operator ", PLUS);
  247.             RetVal = NULL;
  248.         }
  249.         }
  250.         else if (IS_OLST_NODE(TempR) && IS_OLST_NODE(TempL)) {
  251.         Root->ObjType = OBJ_LIST_OBJ;
  252.             Root->U.PObj = AppendLists(TempL->U.PObj, TempR->U.PObj);
  253.         }
  254.         else if ((IS_CTLPT_NODE(TempR) || IS_CRV_NODE(TempR)) &&
  255.              (IS_CTLPT_NODE(TempL) || IS_CRV_NODE(TempL))) {
  256.         Root->ObjType = CURVE_OBJ;
  257.         if (OperReversed)
  258.             Root->U.PObj = MergeCurvesAndCtlPoints(TempR->U.PObj,
  259.                                TempL->U.PObj);
  260.         else
  261.             Root->U.PObj = MergeCurvesAndCtlPoints(TempL->U.PObj,
  262.                                TempR->U.PObj);
  263.         }
  264.         else
  265.         RetVal = NULL;
  266.         break;
  267.     case MINUS:
  268.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  269.         Root->ObjType = NUMERIC_OBJ;
  270.         Root->U.R = TempL->U.R - TempR->U.R;
  271.         }
  272.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  273.         Root->ObjType = VECTOR_OBJ;
  274.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  275.         PT_SUB(Root->U.PObj->U.Vec,
  276.             TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
  277.         }
  278.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  279.         Root->ObjType = MATRIX_OBJ;
  280.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  281.                 MatSubTwo4by4(Root->U.PObj->U.Mat,
  282.             TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
  283.         }
  284.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  285.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  286.         TempLObj = ConvSrfToPolys(TempL);
  287.         TempRObj = ConvSrfToPolys(TempR);
  288.         Root->ObjType = POLY_OBJ;
  289.         Root->U.PObj = BooleanSUB(TempLObj, TempRObj);
  290.         if (Root->U.PObj == NULL) {
  291.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  292.             UpdateCharError("Operator ", MINUS);
  293.             RetVal = NULL;
  294.         }
  295.         }
  296.         else
  297.         RetVal = NULL;
  298.         break;
  299.     case MULT:
  300.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  301.         Root->ObjType = NUMERIC_OBJ;
  302.         Root->U.R = TempL->U.R * TempR->U.R;
  303.         }
  304.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  305.         Root->ObjType = NUMERIC_OBJ;
  306.         Root->U.R = DOT_PROD(TempL->U.PObj->U.Vec,
  307.                      TempR->U.PObj->U.Vec);
  308.         }
  309.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  310.         Root->ObjType = MATRIX_OBJ;
  311.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  312.                 MatMultTwo4by4(Root->U.PObj->U.Mat,
  313.             TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
  314.         }
  315.         else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
  316.         Root->ObjType = VECTOR_OBJ;
  317.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  318.         PT_COPY(Root->U.PObj->U.Vec, TempL->U.PObj->U.Vec);
  319.         PT_SCALE(Root->U.PObj->U.Vec, TempR->U.R);
  320.         }
  321.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  322.         Root->ObjType = MATRIX_OBJ;
  323.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  324.         MatScale4by4(Root->U.PObj->U.Mat,
  325.                     TempL->U.PObj->U.Mat, &TempR->U.R);
  326.         }
  327.         else if (IS_POLY_NODE(TempR) && IS_MAT_NODE(TempL)) {
  328.         Root->U.PObj = TransformObject(TempR->U.PObj,
  329.                            TempL->U.PObj->U.Mat);
  330.         Root->ObjType = POLY_OBJ;
  331.         }
  332.         else if ((IS_MAT_NODE(TempR) && IS_CRV_NODE(TempL)) ||
  333.              (IS_MAT_NODE(TempR) && IS_SRF_NODE(TempL)) ||
  334.              (IS_MAT_NODE(TempR) && IS_OLST_NODE(TempL))) {
  335.         Root->U.PObj = TransformObject(TempL->U.PObj,
  336.                            TempR->U.PObj->U.Mat);
  337.         Root->ObjType = Root->U.PObj->ObjType;
  338.         }
  339.         else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
  340.         Root->ObjType = VECTOR_OBJ;
  341.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  342.         MatMultVecby4by4(Root->U.PObj->U.Vec,
  343.                  TempR->U.PObj->U.Vec, TempL->U.PObj->U.Mat);
  344.         }
  345.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  346.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  347.         TempLObj = ConvSrfToPolys(TempL);
  348.         TempRObj = ConvSrfToPolys(TempR);
  349.         Root->ObjType = POLY_OBJ;
  350.         Root->U.PObj = BooleanAND(TempLObj, TempRObj);
  351.         if (Root->U.PObj == NULL) {
  352.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  353.             UpdateCharError("Operator ", MULT);
  354.             RetVal = NULL;
  355.         }
  356.         }
  357.         else
  358.         RetVal = NULL;
  359.         break;
  360.     case DIV:
  361.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {  /* Numeric div. */
  362.         Root->ObjType = NUMERIC_OBJ;
  363.         if (Root->Right->U.R != 0.0) {
  364.             Root->U.R = TempL->U.R / TempR->U.R;
  365.         }
  366.         else {
  367.             *IError = IE_ERR_DIV_BY_ZERO;
  368.             strcpy(CError, "/");
  369.             RetVal = NULL;
  370.         }
  371.         }
  372.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  373.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  374.         TempLObj = ConvSrfToPolys(TempL);
  375.         TempRObj = ConvSrfToPolys(TempR);
  376.         Root->ObjType = POLY_OBJ;
  377.         Root->U.PObj = BooleanCUT(TempLObj, TempRObj);
  378.         if (Root->U.PObj == NULL) {
  379.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  380.             UpdateCharError("Operator ", DIV);
  381.             RetVal = NULL;
  382.         }
  383.         }
  384.         else
  385.         RetVal = NULL;
  386.         break;
  387.     case POWER:
  388.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
  389.         Root->ObjType = NUMERIC_OBJ;
  390.         Root->U.R = pow(TempL->U.R, TempR->U.R);
  391.         }
  392.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  393.         i = (int) TempR->U.R; /* Power MUST be integer in this case. */
  394.         if (!APX_EQ(i, TempR->U.R) || i < -1) {
  395.             *IError = IE_ERR_MAT_POWER;
  396.             strcpy(CError, "^");
  397.             RetVal = NULL;
  398.         }
  399.         Root->ObjType = MATRIX_OBJ;
  400.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  401.         if (i == -1) {             /* Generate the inverse matrix: */
  402.             if (!MatInverseMatrix(TempL->U.PObj->U.Mat,
  403.                       Root->U.PObj->U.Mat)) {
  404.             *IError = IE_ERR_MAT_POWER;
  405.             strcpy(CError, "^");
  406.             RetVal = NULL;
  407.             }
  408.         }
  409.         else {                  /* I must be positive integer. */
  410.             MatGenUnitMat(Root->U.PObj->U.Mat);
  411.             while (i--) MatMultTwo4by4(Root->U.PObj->U.Mat,
  412.                            Root->U.PObj->U.Mat,
  413.                            TempL->U.PObj->U.Mat);
  414.         }
  415.         }
  416.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  417.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  418.         TempLObj = ConvSrfToPolys(TempL);
  419.         TempRObj = ConvSrfToPolys(TempR);
  420.         Root->ObjType = POLY_OBJ;
  421.         Root->U.PObj = BooleanMERGE(TempLObj, TempRObj);
  422.         if (Root->U.PObj == NULL) {
  423.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  424.             UpdateCharError("Operator ", MINUS);
  425.             RetVal = NULL;
  426.         }
  427.         }
  428.         else
  429.         RetVal = NULL;
  430.         break;
  431.     case UNARMINUS:
  432.         if (IS_NUM_NODE(TempR)) {
  433.         Root->ObjType = NUMERIC_OBJ;
  434.         Root->U.R = -TempR->U.R;
  435.         }
  436.         else if (IS_VEC_NODE(TempR)) {
  437.         Root->ObjType = VECTOR_OBJ;
  438.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  439.         PT_COPY(Root->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
  440.         PT_SCALE(Root->U.PObj->U.Vec, -1.0);
  441.         }
  442.         else if (IS_MAT_NODE(TempR)) {
  443.         Root->ObjType = MATRIX_OBJ;
  444.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  445.         R = -1.0;
  446.         MatScale4by4(Root->U.PObj->U.Mat, TempR->U.PObj->U.Mat, &R);
  447.         }
  448.         else if (IS_POLY_NODE(TempR)) {
  449.         Root->ObjType = POLY_OBJ;
  450.         Root->U.PObj = BooleanNEG(TempR -> U.PObj);
  451.         }
  452.         else if (IS_CRV_NODE(TempR)) {
  453.         Root->ObjType = CURVE_OBJ;
  454.         Root->U.PObj = CurveReverse(TempR -> U.PObj);
  455.         }
  456.         else if (IS_SRF_NODE(TempR)) {
  457.         Root->ObjType = SURFACE_OBJ;
  458.         Root->U.PObj = SurfaceReverse(TempR -> U.PObj);
  459.         }
  460.         else
  461.         RetVal = NULL;
  462.         break;
  463.     }
  464.     if (RetVal == NULL && *IError == IPE_NO_ERR) { /* Put general error msg: */
  465.     *IError = IE_ERR_TYPE_MISMATCH;
  466.     switch (Root->NodeKind) {
  467.         case PLUS:
  468.         strcpy(CError, "Operator +");
  469.         break;
  470.         case MINUS:
  471.         strcpy(CError, "Operator -");
  472.         break;
  473.         case MULT:
  474.         strcpy(CError, "Operator *");
  475.         break;
  476.         case DIV:
  477.         strcpy(CError, "Operator /");
  478.         break;
  479.         case POWER:
  480.         strcpy(CError, "Operator ^");
  481.         break;
  482.         case UNARMINUS:
  483.         strcpy(CError, "Operator (unary) -");
  484.         break;
  485.     }
  486.     }
  487.  
  488.     return RetVal;
  489. }
  490.  
  491. /*****************************************************************************
  492. *   If given object is a surface, its polygonal representation object is     *
  493. * returned instead. Otherwise the given pointer is returned as is.           *
  494. *****************************************************************************/
  495. static ObjectStruct *ConvSrfToPolys(ParseTree *Srf)
  496. {
  497.     if (!IS_SRF_NODE(Srf)) return Srf -> U.PObj;
  498.  
  499.     if (Srf -> U.PObj -> U.Srf.Polygons == NULL)
  500.     ComputeSurfacePolygons(Srf -> U.PObj);
  501.  
  502.     return Srf -> U.PObj -> U.Srf.Polygons;
  503. }
  504.